package cn.xchats.rpc.common.core;

import cn.xchats.rpc.common.annotation.RpcReference;
import cn.xchats.rpc.common.annotation.RpcService;
import cn.xchats.rpc.common.dto.BeanMethod;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/*
 *
 *@author teddy
 *@date 2018/7/3
 */
@SuppressWarnings("all")
public class Invoke {

    /**
     * 组装缓存信息
     */
    public static Map<String, BeanMethod> generateInterfaceInfo(Object bean) {
        Class<?> beanClass = bean.getClass();
        Map<String, BeanMethod> beanMap = null;
        if (beanClass.isAnnotationPresent(RpcService.class)) {
            beanMap = new HashMap<>();
            System.out.println("RPC > > > > > cacheBeanName： " + bean.getClass().getName());

            beanMap = convertCacheBeanMethod(bean);
        }
        return beanMap;
    }

    /**
     * 转换参数
     */
    public static <T> T convertCacheBeanMethod(Object bean) {
        Map<String, BeanMethod> beanMap = new HashMap<>();
        Class<?> beanClass = bean.getClass();
        Method[] declaredMethods = beanClass.getDeclaredMethods();

        for (int i = 0; i < declaredMethods.length; i++) {
            Method method = declaredMethods[i];

            String methodParameter = convertMethodParameter(bean, method);
            if (null == methodParameter)
                throw new NullPointerException("方法参数获取有误");

            if (bean.getClass().isAnnotationPresent(RpcService.class)) {
                BeanMethod beanMethod = new BeanMethod();
                //缓存：当前bean实例 & 方法
                beanMethod.setBean(bean);
                beanMethod.setMethod(method);

                //缓存：key:类全名+方法名+ '?参数类型'
                beanMap.put(methodParameter, beanMethod);
            }
        }
        return  (T)beanMap;
    }

    public static String convertMethodParameter(Object bean, Method method) {
        //组装参数类型
        Class<?>[] parameterTypeArray = method.getParameterTypes();
        StringBuilder parameterType = new StringBuilder();
        String parameterTypeString;
        for (int parameterIndex = 0; parameterIndex < parameterTypeArray.length; parameterIndex++) {
            Class<?> parameter = parameterTypeArray[parameterIndex];
            String typeName = parameter.getName();
            parameterType.append(typeName);
            parameterType.append(",");
        }
        //最后一个为,则删除
        int splitLastIndexOf = parameterType.lastIndexOf(",");
        if (0 != parameterType.length() && splitLastIndexOf == parameterType.length() - 1)
            parameterTypeString = parameterType.substring(0, parameterType.length() - 1);
        else
            parameterTypeString = parameterType.toString();

        String interfaceTypeName = null;
        if (bean.getClass().isAnnotationPresent(RpcService.class))
            interfaceTypeName = bean.getClass().getAnnotation(RpcService.class).RpcInterface().getTypeName();
        else //(bean.getClass().isAnnotationPresent(RpcReference.class))
            interfaceTypeName = ((Class) bean).getInterfaces()[0].getTypeName();

        String currentBeanMethod = new StringBuilder()
                //.append(beanClass.getCanonicalName())
                .append(interfaceTypeName)
                .append(".")
                .append(method.getName())
                .append("&methodParameter=")
                .append(parameterTypeString)
                .toString();

        System.out.println("RPC > > > > > cacheMethod： " + currentBeanMethod);
        return currentBeanMethod;
    }
}
